package ejb.contentManagement;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.commons.io.IOUtils;

import ejb.dto.ExcursionDTO;
import entities.Excursion;
import entities.Location;


@Stateless
public class ExcursionBean implements ExcursionMgr {
	
	@PersistenceContext
    private EntityManager em;
	
	/**
	 * Retrieve entity Excursion from the associated Id
	 * @param id
	 * @return entity Excursion associated to the <code>id</code>
	 */
	public Excursion getExcursion(int id) {
		return em.find(Excursion.class, id);
	}
	
	/**
	 * Retrieve all Excursion entities
	 * @return all Excursion entities
	 */
	public List<Excursion> getAllExcursions() {
    	return em.createNamedQuery("Excursion.findAll", Excursion.class)
                .getResultList();
    }
	
	/**
	 * Retrieve entity Excursion from the associated Id and convert it to corresponding ExcursionDTO
	 */
	@Override
	public ExcursionDTO getExcursionDTO(int id) {
		return  convertToDTO(getExcursion(id));
    }
	
	/**
	 * Retrieve all Excursion entities and convert them into corresponding list of ExcursionDTO
	 */
	@Override
	public List<ExcursionDTO> getAllExcursionsDTO() {
		List<Excursion> list = getAllExcursions();
		List<ExcursionDTO> newList = new ArrayList<ExcursionDTO>();
		for(Excursion obj : list) {
			newList.add(convertToDTO(obj));
		}
		return newList;
	}
	
	/**
	 * Retrieve Excursion entities corresponding to specified Location and convert them 
	 * into corresponding list of ExcursionDTO
	 */
	@Override
	public List<ExcursionDTO> getAllExcursionsByLocation(int locationId){
		List<Excursion> list = em.createNamedQuery("Excursion.findByLocation", Excursion.class).setParameter("l", em.find(Location.class,  locationId)).getResultList();
		List<ExcursionDTO> newList = new ArrayList<ExcursionDTO>();
		for(Excursion obj : list) {
			newList.add(convertToDTO(obj));
		}
		return newList;
	}

	/**
	 * Convert entity Excursion (parameter <code>e</code>) into corresponding ExcursionDTO 
	 * @param e
	 * @return converted ExcursionDTO
	 */
	public static ExcursionDTO convertToDTO(Excursion e) {
		if(e == null) {
			return null;
		}
		ExcursionDTO dto = new ExcursionDTO();
		dto.setId(e.getId());
		dto.setName(e.getName());
		dto.setPrice(e.getPrice());
		dto.setDescription(e.getDescription());
		dto.setLocation(LocationBean.convertToDTO(e.getLocation()));
		return dto;
	}
	
	/**
	 * Retrieve entity Excursion from the associated Id and delete the corresponding element from the database
	 */
	@Override
	@RolesAllowed({"ADMINS"})
	public boolean deleteExcursion(int id) {
		try{
			em.remove(em.find(Excursion.class, id));
			em.flush();
		}
		//Catch exceptions in the delete operation from database
		catch(Exception e){
			return false;
		}
		return true;
	}
	
	/**
	 * Create entity Excursion from corresponding ExcursionDTO and update corresponding element in database
	 */
	@Override
	@RolesAllowed({"ADMINS"})
	public boolean updateExcursion(ExcursionDTO updatedExcursion) {
		if(updatedExcursion.getName().equals("") || 
			updatedExcursion.getName().startsWith(" ") ||
			updatedExcursion.getName()==null || 
			updatedExcursion.getPrice() < 0 ||
			updatedExcursion.getPrice() > 50000)
			return false;
		try{
			em.merge(new Excursion(updatedExcursion, em.find(Location.class, updatedExcursion.getLocationId())));
			em.flush();
		}
		//catch exceptions in the update operation of database
		catch(Exception e){
			return false;
		}
		return true;
	}
	
	/**
	 * Create entity Excursion from corresponding ExcursionDTO and insert new corresponding element in database
	 */
	@Override
	@RolesAllowed({"ADMINS"})
	public boolean insertExcursion(ExcursionDTO newExcursion) {
		if(newExcursion.getName().equals("") || 
			newExcursion.getPrice()<=0 || 
			newExcursion.getImage() == null || 
			newExcursion.getName().startsWith(" ") || 
			newExcursion.getName()==null || 
			newExcursion.getPrice() < 0 ||
			newExcursion.getPrice() > 50000)
			return false;
		Excursion exc = new Excursion(newExcursion, em.find(Location.class, newExcursion.getLocationId()));		
		try{
			em.persist(exc);
			em.flush();
		}
		//Catch exceptions in the insert operation in database
		catch(Exception e){
			return false;
		}
		try {
			InputStream input = newExcursion.getImage().getInputstream();
			File dest = new File("../eclipseApps/TravelDreamEAR/TravelDreamWeb_war/images/excursions/" + exc.getId() + ".jpg");
			OutputStream output = new FileOutputStream(dest);
			IOUtils.copy(input, output);
			IOUtils.closeQuietly(output);
		    IOUtils.closeQuietly(input);
		}
		//catch exceptions in the image uploading operation 
		catch(Exception e) {
			e.printStackTrace();
		}
		return true;
	}
	
	
}
